
namespace('videomaton');

videomaton.VideoMaton = Class.create({
	
	ORIGINAL_DOC_TITLE: 'Videomaton',
	CANVAS_HEIGHT: 240, //480,
	CANVAS_WIDTH: 320, //640,
	
	SPACE_BAR: 32,
	
	ready: false,
	video: null,
	audio: null,
	canvas: null,
	frames: null,
	startTime: null,
	endTime: null,
	recorder: null, //Audio recorder
	
	ctx: null,
	rafId: null,
	
	counter: null,
	recording: false,
	cameraRunning: false,
	
	initialize: function() {
		var me=this;		
		jQuery.ajaxSettings.traditional = true;
		me.frames = [];
		
		jQuery(document).ready(function() {
			// then run the onDocumentLoaded handler (it can also be invoked after ajax requests)
			me.onDocumentLoaded();
			me.ready = true;
		});
		
		me.counter = new videomaton.Counter({
			counterChangedEvent: function(time) {
				me._updateCounter(time);
			},
			stopEvent: function() {
				me.stop();
			},
			warnTimeRemainingEvent: function(time) {
				me._showWarning(time);
			},
		});
	},
	
	/* dom:loaded event handler to be overwritten by subclasses */
	onDocumentLoaded: function() {
		var me = this;
		me.initExports(window);
		me.canvas = document.createElement('canvas'); // offscreen canvas.
		me.initCamera();
		jQuery(document).keypress(function(e) {
			if (e.which == me.SPACE_BAR) {
				me._spaceBarPressed();
				e.stopPropagation();
			}
		});
	},
	
	initExports: function(exports) {
		exports.URL = exports.URL || exports.webkitURL;

		exports.requestAnimationFrame = exports.requestAnimationFrame ||
		    exports.webkitRequestAnimationFrame || exports.mozRequestAnimationFrame ||
		    exports.msRequestAnimationFrame || exports.oRequestAnimationFrame;

		exports.cancelAnimationFrame = exports.cancelAnimationFrame ||
		    exports.webkitCancelAnimationFrame || exports.mozCancelAnimationFrame ||
		    exports.msCancelAnimationFrame || exports.oCancelAnimationFrame;

		navigator.getUserMedia = navigator.getUserMedia ||
		    navigator.webkitGetUserMedia || navigator.mozGetUserMedia ||
		    navigator.msGetUserMedia;
	},
	
	_spaceBarPressed: function() {
		var me = this;
		
		if (me.recording) {
			me.counter.stop();
		} else {
			me.record();
		}
	},
	
	initCamera: function() {
		var me = this;
		
		me.video = jQuery('video')[0];
		me.video.controls = false;
		
		me.audio = jQuery('audio')[0];

//		  var finishVideoSetup_ = function() {
//		    // Note: video.onloadedmetadata doesn't fire in Chrome when using getUserMedia so
//		    // we have to use setTimeout. See crbug.com/110938.
		    setTimeout(function() {
		      me.video.width = me.CANVAS_WIDTH * 2;//video.clientWidth;
		      me.video.height = me.CANVAS_HEIGHT * 2;// video.clientHeight;
//		      // Canvas is 1/2 for performance. Otherwise, getImageData() readback is
//		      // awful 100ms+ as 640x480.
		me.canvas.width = me.CANVAS_WIDTH;
		me.canvas.height = me.CANVAS_HEIGHT;
		    }, 1000);
//		  };

		navigator.getUserMedia({video: true, audio: true}, function(stream) {
			me.video.src = window.URL.createObjectURL(stream);
			var context = new webkitAudioContext();
			var mediaStreamSource = context.createMediaStreamSource(stream);
			//audio recorder
			me.recorder = new Recorder(mediaStreamSource);
			jQuery(document).focus();
			me.cameraRunning = true;
		}, function(e) {
			alert('Could not init the camera');
		});
	},
	
	record: function() {
		var me = this;
		if (me.cameraRunning && !me.recording) {
			me.ctx = me.canvas.getContext('2d');
			
			me.frames = []; // clear existing frames;
			me.startTime = Date.now();
		
			//toggleActivateRecordButton();
			//$('#stop-me').disabled = false;
			me.recorder.record();
			me.rafId = requestAnimationFrame(function(time){me._drawVideoFrame(time);});
			me.counter.start();
			me.recording = true;
		}
	},
	
	_drawVideoFrame: function(time) {
		var me = this;
	    me.rafId = requestAnimationFrame(function(time){me._drawVideoFrame(time);});

	    me.ctx.drawImage(me.video, 0, 0, me.CANVAS_WIDTH, me.CANVAS_HEIGHT);

	    document.title = 'Recording...' + Math.round((Date.now() - me.startTime) / 1000) + 's';
	    
	    // Read back canvas as webp.
	    //console.time('canvas.dataURL() took');
	    var url = me.canvas.toDataURL('image/webp', 1); // image/jpeg is way faster :(
	    //console.timeEnd('canvas.dataURL() took');
	    me.frames.push(url);
	 
	    // UInt8ClampedArray (for Worker).
		//frames.push(ctx.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT).data);
	
		// ImageData
		//frames.push(ctx.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT));
	},
	
	addTime: function() {
		var me = this;
		
		me.counter.addTime();	
	},
	
	stop: function() {
		var me = this;
		if (me.recording) {
			cancelAnimationFrame(me.rafId);
			me.endTime = Date.now();
			
			//$('#stop-me').disabled = true;
			document.title = me.ORIGINAL_DOC_TITLE;
	
			//toggleActivateRecordButton();
			me.recorder.stop();
	
			console.log('frames captured: ' + me.frames.length + ' => ' +
			            ((me.endTime - me.startTime) / 1000) + 's video');
	
			me.finishRecording();
			me._updateCounter(null);
			me._hideWarning();
			me.recording = false;
		}
	},
	
	finishRecording: function() {
		var me = this;
		
		//var url = opt_url || null;
		//var video = $('#video-preview video') || null;
		//var downloadLink = $('#video-preview a[download]') || null;

//		  if (!video) {
//		    video = document.createElement('video');
//		    video.autoplay = true;
//		    video.controls = true;
//		    video.loop = true;
//		    //video.style.position = 'absolute';
//		    //video.style.top = '70px';
//		    //video.style.left = '10px';
//		    video.style.width = canvas.width + 'px';
//		    video.style.height = canvas.height + 'px';
//		    $('#video-preview').appendChild(video);
//		    
//		    downloadLink = document.createElement('a');
//		    downloadLink.download = 'capture.webm';
//		    downloadLink.textContent = '[ download video ]';
//		    downloadLink.title = 'Download your .webm video';
//		    var p = document.createElement('p');
//		    p.appendChild(downloadLink);
//
//		    $('#video-preview').appendChild(p);
//
//		  } else {
//		    window.URL.revokeObjectURL(video.src);
//		  }

		  // https://github.com/antimatter15/whammy
		  // var encoder = new Whammy.Video(1000/60);
		  // frames.forEach(function(dataURL, i) {
		  //   encoder.add(dataURL);
		  // });
		  // var webmBlob = encoder.compile();

//		  if (!url) {
		  me.frames.pop();
		  var webmBlob = Whammy.fromImageArray(me.frames, 1000 / 60);
		    
		    
		  me.recorder.exportWAV(function(audioBlob) {
		        me.audio.src = window.URL.createObjectURL(audioBlob);
			    var fd = new FormData();
				fd.append('video', webmBlob);
				fd.append('audio', audioBlob);
				
			// 	if (me.formParams) {
			// 		for (var paramName in me.formParams) {
			// 			fd.append(paramName,me.formParams[paramName]);
			// 		}
			// 	}
						
				var req = new XMLHttpRequest();
			// 	req.upload.addEventListener("progress", function(evt) { me._uploadProgress(evt); }, false);
			// 	req.addEventListener("load", function(evt) { me._uploadComplete(evt); }, false);
			// 	req.addEventListener("error", function(evt) { me._uploadFailed(evt); }, false);
			// 	req.addEventListener("abort", function(evt) { me._uploadCanceled(evt); }, false);
				req.open("POST", 'send');
				req.send(fd);
			    
		      });
		    
		    
		    //url = window.URL.createObjectURL(webmBlob);
//		  }
//
//		  video.src = url;
//		  downloadLink.href = url;
	},
	
	_updateCounter: function(time) {
		var me = this;
		if (time != null) {
			jQuery('#counter').html('Grabando, quedan ' + time + ' segundos');			
		} else {
			jQuery('#counter').html('');
		}
	},
	
	_showWarning: function(time) {
		var me = this;
		var warningContainer = jQuery('#warning');
		warningContainer.html('Solo queda bla bla bla, ' + time + ' segundos');	
		warningContainer.show();
	},
	
	_hideWarning: function() {
		jQuery('#warning').hide();
	} 
	
});

